#include"ThreadCache.hpp"
#include"CentralCache.hpp"

void* ThreadCache::Allocate(size_t size)//申请内存对象
{
    assert(size <= MAX_BYTES);//判断申请内存大小是否小于最大申请值
    size_t alignSize=SizeClass::RoundUp(size);//对齐内存大小
    size_t index=SizeClass::Index(size);//获取内存大小对应的索引
    if(!_freeLists[index].Empty())//如果哈希桶中有内存对象
    {
        return _freeLists[index].Pop();
    }
    else//如果哈希桶中没有内存对象
    {
        return FetchFromCentralCache(index,alignSize);//从CentralCache中获取内存对象
    }
}
void ThreadCache::Deallocate(void* ptr, size_t size)//释放内存对象
{
    assert(ptr);
    assert(size<=MAX_BYTES);

    size_t index=SizeClass::Index(size);
    _freeLists[index].Push(ptr);
    if(_freeLists[index].Size()>=_freeLists[index].MaxSize())
    {
        ListTooLong(_freeLists[index],size);
    }

}
void* ThreadCache::FetchFromCentralCache(size_t index,size_t size)//从CentralCache中获取内存对象
{
    //采用慢开始反馈算法，当从CentralCache中获取内存对象时，每次获取的内存对象数量逐渐增加
    size_t batchNum =(_freeLists[index].MaxSize()>SizeClass::NumMoveSize(size) ? SizeClass::NumMoveSize(size): _freeLists[index].MaxSize());
    if(batchNum==_freeLists[index].MaxSize())
    {
        _freeLists[index].MaxSize()+=1;//如果获取的内存对象数量为MaxSize，则将最大值加1
    }
    void* start=nullptr;
    void* end=nullptr;
    size_t actualNum=CentralCache::GetInstance()->FetchRangeObj(start,end,batchNum,size);//从CentralCache中获取内存对象
    assert(actualNum>=1);

    if(actualNum==1)//如果获取的内存对象数量为1，则直接返回
    {
        assert(start==end);
        return start;
    }
    else//如果获取的内存对象数量大于1，将剩下的对象挂到thread cache对应的哈希桶
    {
        _freeLists[index].PushRange(NextObj(start),end,actualNum-1);
        return start;
    }
}
void ThreadCache::ListTooLong(FreeList &list, size_t size)
{
    void* start=nullptr;
    void* end=nullptr;

    list.PopRange(start,end,list.MaxSize());//从list中取出Maxize个内存对象
    CentralCache::GetInstance()->ReleaseListToSpans(start,size);//将内存对象回收给CentralCache
}
